package com.smallstep.hystrix.executor;

import com.netflix.hystrix.exception.HystrixBadRequestException;
import com.netflix.hystrix.exception.HystrixRuntimeException;
import com.smallstep.hystrix.command.FFHystrixCommand;
import com.smallstep.hystrix.entity.FFFallbackMethod;
import com.smallstep.hystrix.entity.FFRequestInfo;
import com.smallstep.hystrix.enums.HystrixKeyEnum;
import com.smallstep.hystrix.exceptions.IFallbackIgnore;
import com.smallstep.hystrix.properties.FFHystrixProperties;
import com.smallstep.hystrix.utils.ApplicationContextUtil;
import com.smallstep.hystrix.utils.FFHystrixFallbackUtil;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;

import java.lang.reflect.Type;
import java.net.URI;

/**
 * @author 李俊
 */
public abstract class FFHystrixHttpClientExecutor<T> {
    private FFRequestInfo ffRequestInfo;
    private URI uri;

    public FFHystrixHttpClientExecutor(FFRequestInfo ffRequestInfo, URI uri) {
        this.ffRequestInfo = ffRequestInfo;
        this.uri = uri;
    }

    public T execute() {
        if (!FFHystrixProperties.getPropertyForBoolean(HystrixKeyEnum.FF_HYSTRIX_CLIENT_ENABLED)) {
            return this.run(this.uri, this.ffRequestInfo.getMethod(), this.ffRequestInfo.getRequestEntity(), this.ffRequestInfo.getResponseType());
        } else {
            FFFallbackMethod fallbackMethod = FFHystrixFallbackUtil.getFallbackMethod(this.ffRequestInfo.toFFRequestKey());
            if (fallbackMethod == null) {
                return this.run(this.uri, this.ffRequestInfo.getMethod(), this.ffRequestInfo.getRequestEntity(), this.ffRequestInfo.getResponseType());
            } else {
                try {
                    return (new FFHystrixCommand<T>(this.ffRequestInfo, fallbackMethod) {
                        protected T run() throws Exception {
                            try {
                                return FFHystrixHttpClientExecutor.this.run(FFHystrixHttpClientExecutor.this.uri,
                                        FFHystrixHttpClientExecutor.this.ffRequestInfo.getMethod(),
                                        FFHystrixHttpClientExecutor.this.ffRequestInfo.getRequestEntity(),
                                        FFHystrixHttpClientExecutor.this.ffRequestInfo.getResponseType());
                            } catch (Exception var3) {
                                Exception e = var3;
                                IFallbackIgnore fallbackIgnore = ApplicationContextUtil.getApplicationContext().getBean(IFallbackIgnore.class);
                                if (fallbackIgnore.isFallbackIgnore(var3)) {
                                    e = new HystrixBadRequestException("ffHystrixBadRequestException", var3);
                                }
                                throw (Exception)e;
                            }
                        }
                    }).execute();
                } catch (HystrixRuntimeException | HystrixBadRequestException var3) {
                    if (var3.getCause() instanceof RuntimeException) {
                        throw (RuntimeException)var3.getCause();
                    } else {
                        throw var3;
                    }
                }
            }
        }
    }

    protected abstract T run(URI var1, HttpMethod var2, HttpEntity<?> var3, Type var4);
}
